/**
 * 全局状态
 */
var store = {
    debug: false,
    state: {
        loginDialog: false,
    },
    setLoginDialog (newValue) {
        this.state.loginDialog = newValue
    },
}

/**
 * 网络请求(全局使用此方法进行请求接口)
 */
var request = {
	/**
	 * 发送post请求(兼容数组)
	 * @param  {String} url      链接
	 * @param  {Object} data     数据集
	 */
	post(url, data, callback = ""){
		$.ajax({
			url: admin_url(url),
			type: 'post',
			dataTyle: 'json',
			contentType:"application/json;charset=utf-8",
			data: JSON.stringify(data),
			success:function(res) {
				if (res.status === 'login') {
					store.setLoginDialog(true);
					if (callback != "") callback(res);
				} else {
					if (callback != "") callback(res);
				}
			},
			error:function(res) {
				res.status  = 'error';
				res.message = res.statusText;
				if (callback != "") callback(res);
			}
		})
	},
}

/**
 * 链接
 */
var locationUrl = {
	/**
	 * 获取链接参数
	 * @param  {String} name 参数名
	 */
	get(name) {
	    var reg = new RegExp("(^|&)" + name + "=([^&]*)(&|$)", "i"); 
	    var r = window.location.search.substr(1).match(reg); 
	    if (r != null) return unescape(r[2]); 
	    return ""; 
	},
	/**
	 * 设置链接参数
	 * @param  {String} name  参数名
	 * @param  {String} value 值
	 */
	set(name, value){
		var loadUrl = location.href;
		var arrUrl  = loadUrl.split('#');
		var url     = arrUrl[0];
		var pattern = name + '=([^&]*)';
	    var replaceText = name+'='+value; 
	    var newUrl = "";
	    if (url.match(pattern)) {
	        var tmp = '/(' + name + '=)([^&]*)/gi';
	        newUrl = url.replace(eval(tmp),replaceText);
	    } else { 
	        if (url.match('[\?]')) { 
	            newUrl = url + '&' + replaceText; 
	        } else {
	            newUrl =  url +'?' + replaceText; 
	        } 
	    }
	    location.href = newUrl+window.location.hash
	}
}

/**
 * localStorage缓存
 */
var storage = {
	/**
	 * 设置缓存
	 * @param {String} key    缓存名称
	 * @param {[type]} value  缓存值
	 * @param {[type]} expire 缓存时长(毫秒)
	 */
	set(key, value, expire){
	    let obj = {
	        data: value,
	        time: Date.now(),
	        expire: expire
	    };
	    localStorage.setItem(key, JSON.stringify(obj));
	},
	/**
	 * 获取缓存
	 * @param  {String} key 缓存名称
	 */
	get(key){
	    let val = JSON.parse(localStorage.getItem(key));
	    if (!val) {
	        return val;
	    }
	    if (Date.now() - val.time > val.expire) {
	        localStorage.removeItem(key);
	        return null;
	    }
	    return val.data;
	}
}
/**
 * 树形数组
 */
var tree = {
	/**
	 * 根据字符串查找当前所在节点
	 * @param  {Array} tree      数组
	 * @param  {String} value    配置的值
	 * @param  {String} field    匹配的字段
	 * @param  {String} children 匹配的字段子类
	 * @param  {Number} level    等级
	 * @return {Object}          当前节点
	 */
	getNode(tree, value, field = "id", children = "children", level = 0){
		if (tree[field] == value) {
	        return tree;
	    } else {
	        if (level > 0) {
	            tree = tree[children] ? tree[children] : [];
	        }
	        for (let i = 0, n = tree.length; i < n; i++) {
	            let node = this.getNode(tree[i], value, field, children, 1)
	            if (node) {
	                return node;
	            }
	        }
	    }
	},
	/**
	 * 数组转树形
	 * @param  {Array} data 需转换的数组
	 * @return {Array}      树形数组  
	 */
	convert(data) {
	    let result = []
	    if (!Array.isArray(data)) {
	        return result
	    }
	    data.forEach(item => {
	        delete item.children;
	    });
	    let map = {};
	    data.forEach(item => {
	        map[item.id] = item;
	    });
	    data.forEach(item => {
	        let parent = map[item.pid];
	        if(parent) {
	            (parent.children || (parent.children = [])).push(item);
	        } else {
	            result.push(item);
	        }
	    });
	    result = result.filter(ele => ele.pid == 0);
	    return result;
	},
	/**
	 * 数组转树形字符串数组
	 * @param  {Array} arr     需转换的数组
	 * @param  {Number} pid    pid值
	 * @param  {String} format 字符串的标识
	 * @param  {Array}  list   遍历数组
	 * @return {Array}         数组
	 */
	convertString(arr, pid = 0, format = "<span class='mk-tree-string'>└</span>", list = []) {
		arr.forEach(function(v, k){
			if (v['pid'] == pid) {
				if (pid != 0) {
					v['treeString'] = format;
				}
				list.push(v)
				tree.convertString(arr, v['id'], "<span class='mk-tree-interval'></span>"+format, list);
			}
		});
		return list;
	},
	/**
	 * 树形数组转二维数组
	 * @param  {Array} data 需转换的数组
	 * @return {Array}      数组
	 */
	revert(data) {
		for (var i = 0; i < data.length; i++) {
			if (data[i].children != undefined) {
				var temp = data[i].children;
				// 删除孩子节点
				delete data[i].children;
				// 孩子节点加入数组末尾
				for (var j = 0; j < temp.length; j++) {
					data.push(temp[j]);
				}
			}
		}
		return data;
	},
}

/**
 * 公共函数
 */
var common = {
	/**
	 * 二维数组根据字段返回一维数组
	 * @param  {Array}  arr  数组
	 * @param  {String} name 字段
	 * @return {Array}       一维数组
	 */
	arrayColumn(arr, name) {
		let val = [];
		arr.forEach(function(item,index) {
		    val.push(item[name]);
		})
		return val;
	},
	/**
	 * 文件排序(文件夹永远在最顶部)
	 * @param  {Array}  arr   数组
	 * @return {Array}        数组
	 */
	fileOrder(arr) {
		arr.sort((a,b) => {
			if ( a['folder'] === 1 ) {
				let x = a['folder'];
				let y = b['folder'];
				return y-x;
			}
		})
	},
	/**
	 * 二维数组排序
	 * @param  {Array}  arr   数组
	 * @param  {String} name  字段
	 * @param  {String} order 递减/递增排序
	 * @return {Array}        数组
	 */
	compare(arr, name, order = "desc") {
		arr.sort((a,b) => {
			let x = a[name];
			let y = b[name];
			return order === 'desc' ? y-x : x-y;
		})
	},
	/**
	 * 获取数组某匹配值的下标
	 * @param  {Array} arr    数组
	 * @param  {String} value 匹配值
	 * @param  {String} field 匹配字段
	 * @return {Number}       下标
	 */
	arrayIndex(arr, value, field = "id"){
	    let index = -1;
	    arr.forEach(function(val, key) {
	        if (val[field] == value) {
	            index = key;
	        }
	    });
	    return index;
	},
	/**
	 * 返回随机默认去掉了容易混淆的字符oOLl,9gq,Vv,Uu,I1
	 */
	id() {
		var len    = 36;
		var chars  = 'ABCDEFGHJKMNPQRSTWXYZabcdefhijkmnprstwxyz2345678';
		var maxPos = chars.length;
		var id = '';
		for (i = 0; i < len; i++) {
			id += chars.charAt(Math.floor(Math.random() * maxPos));
		}
		return id;
	},
	/**
	 * 高级字段(自定义参数)
	 */
	formType() {
		return [
	        {title: "字符", name: "text", bind: "el-input", value: ""},
	        {title: "文本域", name: "textarea", bind: "el-input", type: "textarea", value: ""},
	        {title: "编辑器", name: "editor", bind: "mk-editor",value: ""},
	        {title: "设置链接", name: "link", bind: "mk-link", value: ""},
	        {title: "图片上传", name: "imageUpload", bind: "mk-file-select", type: "image", value: ""},
	        {title: "文件上传", name: "fileUpload", bind: "mk-file-select", type: "file", value: ""},
	        {title: "图片列表", name: "imageList", bind: "mk-file-list-select", type:"image", value: []},
	        {title: "文件列表", name: "fileList", bind: "mk-file-list-select", type:"file", value: []},
	        {title: "数组列表", name: "arrayList", bind: "mk-array", type:"array", value: []},
	        {title: "颜色选择器", name: "colorPicker", bind: "el-color-picker", value: ""},
	        {title: "城市级联选择器", name: "cascader", bind: "el-cascader", value: []},
	        {title: "开关", name: "switch", bind: "el-switch", value: false},
	        {title: "滑块", name: "slider", bind: "el-slider", value: 0},
	        {title: "评分", name: "rate", bind: "el-rate", value: ""},
	        {title: "计数器", name: "inputNumber", bind: "el-input-number", value: ""},
            {title: "日期时间", name: "datetime", bind: "el-date-picker", type: "datetime", format: "yyyy-MM-dd HH:mm:ss", valueFormat: "yyyy-MM-dd HH:mm:ss", value: ""},
	    ];
	},
	/**
	 * 颜色板自定义
	 */
	predefineColors() {
		return [
            '#ff4500',
            '#ff8c00',
            '#ffd700',
            '#90ee90',
            '#00ced1',
            '#1e90ff',
            '#c71585',
            'rgba(255, 69, 0, 0.68)',
            'rgb(255, 120, 0)',
            'hsv(51, 100, 98)',
            'hsva(120, 40, 94, 0.5)',
            'hsl(181, 100%, 37%)',
            'hsla(209, 100%, 56%, 0.73)',
            '#c7158577'
        ];
	},
	/**
	 * 判断是否为对象格式
	 * @param  {Object}  object 
	 * @return {Boolean}   
	 */
	isObj(object) {
	    return object && typeof(object) == 'object' && Object.prototype.toString.call(object).toLowerCase() == "[object object]";
	},
	/**
	 * 判断是否为数组格式
	 * @param  {Object}  object 
	 * @return {Boolean}   
	 */
	isArray(object) {
	    return object && typeof(object) == 'object' && object.constructor == Array;
	},
	/**
	 * 获取对象长度
	 * @param  {Object}  object 
	 * @return {Number}   
	 */
	getLength(object) {
	    var count = 0;
	    for(var i in object) count++;
	    return count;
	},
	/**
	 * 判断两个json是否相等
	 * @param  {Object}  objA   
	 * @param  {Object}  objB  
	 * @return {Boolean}   
	 */
	isChangeObj(objA, objB) {
	    if(! common.isObj(objA) || ! common.isObj(objB)) return false; //判断类型是否正确
	    if(common.getLength(objA) != common.getLength(objB)) return false; //判断长度是否一致
	    return common.compareObj(objA, objB, true); //默认为true
	},
	/**
	 * 循环判断两个json属性是否相等
	 * @param  {Object}  objA   
	 * @param  {Object}  objB  
	 * @return {Boolean}   
	 */
	compareObj(objA, objB, flag) {
	    for(var key in objA) {
	        if(!flag) //跳出整个循环
	            break;
	        if(!objB.hasOwnProperty(key)) {
	            flag = false;
	            break;
	        }
	        if(! common.isArray(objA[key])) { //子级不是数组时,比较属性值
	            if(objB[key] != objA[key]) {
	                flag = false;
	                break;
	            }
	        } else {
	            if(! common.isArray(objB[key])) {
	                flag = false;
	                break;
	            }
	            var oA = objA[key],
	                oB = objB[key];
	            if(oA.length != oB.length) {
	                flag = false;
	                break;
	            }
	            for(var k in oA) {
	                if(!flag) //这里跳出循环是为了不让递归继续
	                    break;
	                flag = common.compareObj(oA[k], oB[k], flag);
	            }
	        }
	    }
	    return flag;
	},
	/**
	 * 获取两个日期的时间差
	 * @param dt1,dt2 yyyy-MM-dd or yyyy-MM-dd hh:mm:ss
	 * 返回值单位为：分钟
	 */
	getIntervalMinutes(dt1, dt2) {
		if (typeof (dt1) == "string") {
		    dt1 = new Date(dt1.replace(/-/, '/'));
		    dt2 = new Date(dt2.replace(/-/, '/'));
		}
		var res = Math.abs(dt2 - dt1);
		if (isNaN(res))throw Error("invalid dates arguments");return res / (1000 * 60);
	},
	/**
	 * 日期时间格式
	 * @return {String} yyyy-MM-dd hh:mm:ss
	 */
	dateTime(para = '') {
		let date = para === '' ? new Date() : new Date(para);
		let year = date.getFullYear(); // 年
		let month = date.getMonth() + 1; // 月
		month = month < 10 ? "0" + month : month; // 如果只有一位，则前面补零
		let day = date.getDate(); // 日
		day = day < 10 ? "0" + day : day; // 如果只有一位，则前面补零
		let hour = date.getHours(); // 时
		hour = hour < 10 ? "0" + hour : hour; // 如果只有一位，则前面补零
		let minute = date.getMinutes(); // 分
		minute = minute < 10 ? "0" + minute : minute; // 如果只有一位，则前面补零
		let second = date.getSeconds(); // 秒
		second = second < 10 ? "0" + second : second; // 如果只有一位，则前面补零
		return `${year}-${month}-${day} ${hour}:${minute}:${second}`;
	},
	/**
	 * @return 时间过去了多久，刚刚...
	 */
	getTimeDiff(datetimeStr) {
		if (undefined === datetimeStr || null == datetimeStr || 'null' == datetimeStr || '' === datetimeStr || datetimeStr == 0) {
		    return "";
		}
		var minutes = this.getIntervalMinutes(datetimeStr, this.dateTime())
		if (minutes < 1) { // 0-2分钟：刚刚
		    return '刚刚'
		}
		if (minutes >= 1 && minutes <= 59) { // 3-59分钟：x分钟前
		    return Math.floor(minutes) + '分钟前'
		}
		var hours = minutes / 60
		if (hours <= 24) {
		    return Math.floor(hours) + '小时前'
		}
		var days = hours / 24
		if (days > 1 && days < 4) { // 1天-3天：x天前
		    return Math.floor(days) + '天前'
		}
		var year = datetimeStr.substring(0, 4)
		var nowyear = new Date().getFullYear()
		if (year != nowyear) {
		    return datetimeStr.substring(0, 10)
		} else {
		    return Number(datetimeStr.substring(5, 7)) + '月' + Number(datetimeStr.substring(8, 10)) + '日'
		}
	}
}

/**
 * 文件
 */
var file = {
	/**
	 * 获取文件大小
	 * @param  {Number} Bytes 字节
	 */
	getSize(Bytes) {
	    if (null == Bytes || Bytes == '') {
	        return "0 Bytes";
	    }
	    var unitArr = new Array("Bytes","KB","MB","GB","TB","PB","EB","ZB","YB");
	    var index = 0,
	    srcsize = parseFloat(Bytes);
		index = Math.floor(Math.log(srcsize) / Math.log(1024));
	    var size = srcsize / Math.pow(1024,index);
	    size = size.toFixed(2);
	    return size+unitArr[index];
	},
	/**
	 * 文件类型、名称
	 * @param  {String} url 文件链接
	 * @return {Object}     文件类型、名称
	 */
	getType(url) {
		let arr    = url.split('.');
		let suffix = arr[arr.length-1];
		var value  = {};
		switch(suffix){
			case ('png'):
			case ('jpg'):
			case ('jpeg'):
			case ('bmp'):
			case ('gif'):
			case ('ico'):
				value['name'] = "图片";
				value['type'] = "image";
				break;
			case ('mp4'):
			case ('m2v'):
			case ('mkv'):
			case ('wmv'):
				value['name'] = "视频";
				value['type'] = "video";
				break;
			case ('mp3'):
			case ('wav'):
				value['name'] = "音频";
				value['type'] = "audio";
				break;
			case ('txt'):
				value['name'] = "文本";
				value['type'] = "txt";
				break;
			case ('xls'):
			case ('xlsx'):
				value['name'] = "Excel文件";
				value['type'] = "xls";
				break;
			case ('doc'):
			case ('docx'):
				value['name'] = "Word文件"
				value['type'] = "word";
				break;
			case ('pdf'):
				value['name'] = "PDF文件"
				value['type'] = "pdf";
				break;
			case ('ppt'):
				value['name'] = "PPT文件"
				value['type'] = "ppt";
				break;
			case ('rar'):
			case ('zip'):
				value['name'] = "压缩文件";
				value['type'] = "zip";
				break;
			case ('dll'):
				value['name'] = "动态链接库";
				value['type'] = "dll";
				break;
			case ('torrent'):
				value['name'] = "BT文件";
				value['type'] = "torrent";
				break;
			case ('dwt'):
				value['name'] = "Dreamweaver文件";
				value['type'] = "dwt";
				break;
			case ('psd'):
				value['name'] = "Photoshop文件";
				value['type'] = "psd";
				break;
			case ('swf'):
				value['name'] = "Flash文件";
				value['type'] = "swf";
				break;
			default:
				value['name'] = "未知文件"
				value['type'] = "other";
				break;
		}
		return value;
	}
}
/**
 * 删除数组中某些对象
 */
Array.prototype.remove = function (arr) {
	let scene = JSON.parse(JSON.stringify(this));
	scene = scene.filter(item => {
      return arr.indexOf(item.prop) === -1;
    })
    return scene;
}
/**
 * 获取数组中某些对象
 */
Array.prototype.only = function (arr) {
	let scene = [];
	this.forEach(function (item, index) {
		arr.forEach(function (prop, key) {
			if (item.prop === prop) {
				scene.push(item);
			}
		})
	})
	return scene;
}
/**
 * 获取url
 */
function admin_url(url) {
	if (url.split('/').length === 2) {
		// 系统路由
		var newUrl = adminSplitUrl.replace('decoration/your-link', url);
	} else {
		// 插件路由
		var newUrl = pluginSplitUrl.replace('plugin_path', url).replace('/index.html', '');
	}
	let str = newUrl.indexOf('?') === -1 ? '?' : '&';
	return newUrl + str + 'lang=' + language;
}
/**
 * 获取语言
 */
function lang(name) {
    return typeof langParameter[name] === "undefined" || langParameter[name] === "" ? name : langParameter[name];
}